package com.xdqzy.baseline.common.utils;

import com.xdqzy.baseline.common.model.PageModel;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;

/**
 * <Description> 对象转换工具<br>
 *
 * @author qss<br>
 * @version 1.0<br>
 * @taskId <br>
 * @CreateDate 2019年9月17日 <br>
 */
@Slf4j
public class ModelMapperUtil {

    /**
     * 定义基础modelMapper对象
     */
    private static ModelMapper modelMapper;

    static {
        modelMapper = new ModelMapper();
        // 精准匹配a
        modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
    }

    /**
     * Description: dto转换-通用精确匹配 (精确匹配是指只copy相同属性名的值) <br>
     * 自定义匹配规则请参考：http://modelmapper.org/getting-started/ 的‘Explicit Mapping’部分<br>
     *
     * @param source          源对象
     * @param destinationType 目标对象类型
     * @param <D>             泛型对象
     * @return <br>
     */
    public static <D> D strictMap(Object source, Class<D> destinationType) {
        if (Objects.isNull(source)) {
            return null;
        }
        return modelMapper.map(source, destinationType);
    }

    /**
     * Description: List&lt;dto>转换<br>
     *
     * @param source        源对象
     * @param componentType 目标对象类型
     * @param <D>           泛型对象
     * @return <br>
     */
    @SuppressWarnings("unchecked")
    public static <D> List<D> strictMapList(Object source, final Class<D> componentType) {
        if (Objects.isNull(source)) {
            return Lists.newArrayList();
        }
        List<D> list = new ArrayList<>();
        List<Object> objectList = (List<Object>) source;
        for (Object obj : objectList) {
            list.add(modelMapper.map(obj, componentType));
        }
        return list;
    }

    /**
     * Description: dto转换-通用精确匹配 (精确匹配是指只copy相同属性名的值) <br>
     * 自定义匹配规则请参考：http://modelmapper.org/getting-started/ 的‘Explicit Mapping’部分<br>
     *
     * @param source          源对象
     * @param destinationType 目标对象类型
     * @param <D>             泛型对象
     * @return <br>
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    public static <D> PageModel<D> strictPageModel(PageModel source, Class<D> destinationType) {
        if (Objects.isNull(source)) {
            return null;
        }

        PageModel<D> copy = new PageModel<>();
        copy.setPageNum(source.getPageNum());
        copy.setPageSize(source.getPageSize());
        copy.setPages(source.getPages());
        copy.setTotal(source.getTotal());
        List<Object> objectList = source.getResultList();
        List<D> list = new ArrayList<>();

        for (Object obj : objectList) {
            list.add(modelMapper.map(obj, destinationType));
        }

        copy.setResultList(list);
        return copy;
    }


    /**
     * javabean转map
     *
     * @param bean
     * @return
     * @throws Exception
     */
    public static Map<String, Object> bean2map(Object bean) {
        Map<String, Object> map = new HashMap<>();
        try {
            //获取JavaBean的描述器
            BeanInfo b = Introspector.getBeanInfo(bean.getClass(), Object.class);
            //获取属性描述器
            PropertyDescriptor[] pds = b.getPropertyDescriptors();
            //对属性迭代
            for (PropertyDescriptor pd : pds) {
                //属性名称
                String propertyName = pd.getName();
                //属性值,用getter方法获取
                Method m = pd.getReadMethod();
                //用对象执行getter方法获得属性值
                Object properValue = m.invoke(bean);
                //把属性名-属性值 存到Map中
                map.put(propertyName, properValue);
            }
        } catch (Exception e) {
            log.error("javaBean转换map失败!", e);
        }
        return map;
    }

    /**
     * 私有构造
     */
    private ModelMapperUtil() {
    }
}
